#ifndef EXCEPTION_H
#define EXCEPTION_H

#ifdef DEBUG_BUILD
#define ENABLE_STACKTRACE if(DEBUG_BUILD) {ERR(common::Logger::logger(), common::Error::stacktrace());}
#else
#define ENABLE_STACKTRACE
#endif
#include <exception>
#include <string>
#include <boost/stacktrace/stacktrace.hpp>

#include "errcode.hpp"

namespace common {

class Error final : public std::exception {
	error error_;
	std::string message_;
public:
	Error() = delete;
	explicit Error(const error error_code)
		: error_(error_code) {}

	Error(const error error_code, std::string  message)
		: error_(error_code), message_(std::move(message)) {}

	[[nodiscard]] const char* what() const noexcept override {
		const std::string ch = (std::to_string(static_cast<int>(error_)) + ":" + message_);
		const auto wh = new char[ch.size()+1];
		memcpy(wh, ch.data(), ch.size()+1);
		return wh;
	}

	static const std::string& stacktrace() noexcept {
		auto traces = boost::stacktrace::stacktrace().as_vector();
		static auto cause = std::string("Caused by ");
		auto help = std::string("");
		auto it_begin = traces.begin();
		it_begin += 3;
		auto it_end = traces.end();
		it_end -= 6;
		while (it_begin != it_end) {
			cause += (help + to_string(*it_begin) + '\n');
			help = "by ";
			++it_begin;
		}
		return cause;
	}
};

}
#endif // !EXCEPTION_H
